<?php

class Pet extends CActiveRecord
{
    public $attackSkills = array();
    public $helpSkills = array();

    private $_fightVars = array();

    //孤僻型/懦弱型/可爱型/好动型/勇敢型/狂暴型/阴险型/冷酷型/冷静型
    public static $features=array(
        array(desc=>'孤僻型','physicalAttackRate'=>40,'skillAttackRate'=>20,'skillHelpRate'=>20,'defendRate'=>20),
        array(desc=>'懦弱型','physicalAttackRate'=>40,'skillAttackRate'=>20,'skillHelpRate'=>20,'defendRate'=>20),
        array(desc=>'可爱型','physicalAttackRate'=>30,'skillAttackRate'=>20,'skillHelpRate'=>40,'defendRate'=>10),
        array(desc=>'好动型','physicalAttackRate'=>30,'skillAttackRate'=>40,'skillHelpRate'=>20,'defendRate'=>10),
        array(desc=>'勇敢型','physicalAttackRate'=>40,'skillAttackRate'=>40,'skillHelpRate'=>20,'defendRate'=>0),
        array(desc=>'狂暴型','physicalAttackRate'=>20,'skillAttackRate'=>60,'skillHelpRate'=>20,'defendRate'=>0),
        array(desc=>'阴险型','physicalAttackRate'=>0,'skillAttackRate'=>40,'skillHelpRate'=>60,'defendRate'=>0),
        array(desc=>'冷酷型','physicalAttackRate'=>0,'skillAttackRate'=>70,'skillHelpRate'=>30,'defendRate'=>0),
        array(desc=>'冷静型','physicalAttackRate'=>0,'skillAttackRate'=>50,'skillHelpRate'=>50,'defendRate'=>0),
    );

    public static $states = array(
        'normal',
        'torpid',   //麻痹 无法使用技能
        'stiff',    //僵硬 强制防御
        'sleep',    //睡眠 无法行动
        'poisoned', //中毒 每回合受到持续伤害  伤害值公式与技能有关
        'frightened',//恐惧 防御几率增加20%
        'dexterityChanged',  //高速移动 敏捷增加20%
        'strengthChanged',  //
        'enduranceChanged', //
        'spiritChanged',
        'lightShield',  //光之壁    令对方攻击无效
        'mirrorShield'  //镜之壁    反弹对方的攻击伤害
    );
    
	public static function loadPet($id)
	{
		$pet=self::loadPetFromCache($id);
		if($pet!==null)
			return $pet;
		$pet=self::loadPetFromDb($id);
		if($pet!==null)
			self::savePetToCache($pet);
		return $pet;
	}

	public static function ListPet($criteria)
	{
		return self::model()->findAll($criteria);
	}

	public static function countPet($criteria)
	{
		return self::model()->count($criteria);
	}

	public static function savePet(&$pet)
	{
		$ret=self::savePetToDb($pet);
		if($ret)
			self::savePetToCache($pet);
		return $ret;	
	}
	
	public static function deletePet(&$pet)
	{
		$ret=self::deletePetFromDb($pet);
		if($ret)
			self::deletePetFromCache($pet);
		return $ret;	
	}

	public static function loadPetFromCache($id)
	{
		//TODO:
		return null;
	}

	public static function savePetToCache(&$pet)
	{
		//TODO:
		return true;
	}

	public static function deletePetFromCache(&$pet)
	{
		//TODO:
		return true;
	}

	public static function loadPetFromDb($id)
	{
		return self::model()->find('id=:id', array(':id'=>$id));
	}

	public static function savePetToDb(&$pet)
	{
		return $pet->save();
	}

	public static function deletePetFromDb(&$pet)
	{
		return $pet->delete();
	}
 
    public function &__get($name)
    {
        if (array_key_exists($name, $this->_fightVars))
            return $this->_fightVars[$name];
        else
            return parent::__get($name);
    }
    
    public function __set($name,$value)
    {
        if (array_key_exists($name, $this->_fightVars))
            $this->_fightVars[$name] = $value;
        else
            parent::__set($name,$value);
    }
    
    public function __isset($name)
    {
        if (array_key_exists($name, $this->_fightVars))
            return isset($this->_fightVars[$name]);
        else
            return parent::__isset($name);            
    }
    
    public function __unset($name)
    {
        if (array_key_exists($name, $this->_fightVars))
            unset($this->_fightVars[$name]);
        else
            parent::__unset($name);     
    }
    
    public function __call($m, $a)
    {
        if (strncmp($m, 'set', 3)==0) {
            $e = strtolower(substr($m, 3));
            $v = &$this->_fightVars[$e];
            if (isset($v)) {
                $v = $a[0];
                if(is_numeric($v) && $v<0) $v = 0;
                return;
            }
            else
                return parent::__call($m, $a);
        }
        elseif (strncmp($m, 'change', 6)==0) {
            $e = strtolower(substr($m, 6));
            $v = &$this->_fightVars[$e];
            if (isset($v)) {
                $v += $a[0];
                if($v<0) $v = 0;
                return;
            }
            else
                return parent::__call($m, $a);
        }
        else {
            return parent::__call($m, $a);
        }
    }

    public function beforeFight()
    {
        $fightVars = &$this->_fightVars;

        $featureInfo=&Pet::$features[$this->feature];
        $fightVars['physicalAttackRate']=$featureInfo['physicalAttackRate'];
        $fightVars['skillAttackRate']=$featureInfo['skillAttackRate'];
        $fightVars['skillHelpRate']=$featureInfo['skillHelpRate'];
        $fightVars['defendRate']=$featureInfo['defendRate'];        
        $fightVars['lastingEffects']=array();
        $fightVars['state']='normal';
        $fightVars['defending']=false;
        $fightVars['attackFree']=false;             
        $fightVars['attackReflect']=false;
        
        $backupItems=array(
            'state',
            'defending',
            'attackFree',
            'attackReflect',
            'physicalAttackRate',
            'skillAttackRate',
            'skillHelpRate',
            'defendRate',
            'endurance',
            'dexterity',
            'spirit',
            'hpMax',
            'mpMax',
            'attack',
            'defence',
            'hitRate',
            'dodge',
        );
        
        $fightVars['_backup']=array();
        $backup = &$fightVars['_backup'];
        foreach($backupItems as &$item)
            $backup[$item]=$this->$item;
    }
    
    public function afterFight()
    {
        $this->_fightVars = array();
    }

    public function beforeFightRound()
    {
    }
    
    public function afterFightRound()
    {
        $backup = &$this->_fightVars['_backup'];    
        foreach($backup as $k=>&$v)
            $this->$k=$v;
    }
    
    public function recoverHp()
    {
        $this->hp=$this->hpMax;
    }
    
    public function recoverMp()
    {
        $this->mp=$this->mpMax;
    }

    public function changeHp($n)
    {
        $this->setHp($this->hp+$n);
    }

    public function setHp($n)
    {
        $this->hp=$n;
        if($this->hp>$this->hpMax)
            $this->hp=$this->hpMax;
        elseif($this->hp<0)
            $this->hp=0;
    }

    public function changeMp($n)
    {
        $this->setMp($this->mp+$n);
    }
    
    public function setMp($n)
    {
        $this->mp=$n;
        if($this->mp>$this->mpMax)
            $this->mp=$this->mpMax;
        elseif($this->mp<0)
            $this->mp=0;        
    }
    
    public function changeEndurance($n)
    {
        setEndurance($this->endurance+$n);
    }
    
    public function setEndurance($n)
    {
        $this->endurance=$n;
        if($this->endurance<0) $this->endurance=0;
        $this->calculateStatistic();
    }

    public function changeStrength($n)
    {
        $this->setStrength($this->strength+$n);
    }
    
    public function setStrength($n)
    {
        $this->strength=$n;
        if($this->strength<0) $this->strength=0;
        $this->calculateStatistic();
    }
    
    public function changeDexterity($n)
    {
        $this->setDexterity($this->dexterity+$n);    
    }
    
    public function setDexterity($n)
    {
        $this->dexterity=$n;
        if($this->dexterity<0) $this->dexterity=0;
        $this->calculateStatistic();
    }
    
    public function changeSpirit($n)
    {
        $this->setSpirit($this->spirit+$n);
    }

    public function setSpirit($n)
    {
        $this->spirit=$n;
        if($this->spirit<0) $this->spirit=0;
        $this->calculateStatistic();
    }
            
    public function changeAttributes($attributes)
    {
        if(isset($attributes['endurance'])){
            $attributes['endurance']+=$this->endurance;
        }
        if(isset($attributes['strength'])){
            $attributes['strength']+=$this->strength;
        }
        if(isset($attributes['dexterity'])){
            $attributes['dexterity']+=$this->dexterity;
        }
        if(isset($attributes['spirit'])){
            $attributes['spirit']+=$this->spirit;
        }
        $this->setAttribute($attributes);
    }
    
    public function setAttributes($attributes)
    {
        if(isset($attributes['endurance'])){
            $this->endurance=$attributes['endurance'];
            if ($this->endurance<0) $this->endurance=0;
        }
        if(isset($attributes['strength'])){
            $this->strength=$attributes['strength'];
            if ($this->strength<0) $this->strength=0;
        }
        if(isset($attributes['dexterity'])){
            $this->dexterity=$attributes['dexterity'];
            if ($this->dexterity<0) $this->dexterity=0;
        }
        if(isset($attributes['spirit'])){
            $this->spirit=$attributes['spirit'];
            if ($this->spirit<0) $this->spirit=0;
        }
        $this->calculateStatistic();        
    }
    
    public function calculateStatistic()
    {
        $this->hpMax=(int)(($this->endurance*3.1 + $this->strength*1 + $this->dexterity*0.2 + $this->spirit*0.5)/100);
        $this->mpMax=(int)(($this->endurance*0.3 + $this->strength*0.5 + $this->dexterity*1 + $this->spirit*3)/100);
        $this->attack=(int)(($this->endurance*1 + $this->strength*2.4 + $this->dexterity*0.2)/100);
        $this->defence=(int)(($this->endurance*1.8 + $this->strength*1.2 + $this->dexterity*0.2)/100);
        $this->hitRate=(int)(($this->strength*1.4 + $this->dexterity*1.5 + $this->spirit*0.5)/100);
        $this->dodge=(int)(($this->dexterity*2)/100);
    }
    
    public function alive()
    {
        return $this->hp>0;
     }
                 
    // below are AR functions
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }
    
    public function tableName()
    {
        return 'Pet';
    }

    public function rules()
    {
        return array(
        );
    }

    public function attributeLabels()
    {
        return array(
        );
    }
    
    protected function beforeSave()
    {
        if($this->getIsNewRecord())
            $this->createDt=new CDbExpression('NOW()');
        
        $this->attackSkills = serialize($this->attackSkills);
        $this->helpSkills = serialize($this->attackSkills);
        return true;
    }
    
    protected function afterSave()
    {
        $this->attackSkills = unserialize($this->attackSkills);
        $this->helpSkills = unserialize($this->helpSkills);        
    }
    
    protected function afterFind()
    {
        $this->attackSkills = unserialize($this->attackSkills);
        $this->helpSkills = unserialize($this->helpSkills);    
    }
}

?>